from datetime import timedelta

from celery import Celery, platforms
from kombu import Queue

from apps import app
from apps.foundation import log, db
from apps.logconfig import set_task_config
from config import CELERY_BACKEND, CELERY_BROKERS
from config import SEND_EXCEPTION_MSG

platforms.C_FORCE_ROOT = True


def make_celery(app):
    celery = Celery(app.import_name, broker=CELERY_BROKERS, backend=CELERY_BACKEND)
    celery.conf.update(app.config)
    TaskBase = celery.Task

    class ContextTask(TaskBase):
        abstract = True

        def __call__(self, *args, **kwargs):
            with app.app_context():
                set_task_config()
                result = None
                try:
                    result = TaskBase.__call__(self, *args, **kwargs)
                    db.session.close()
                except Exception as e:
                    db.session.rollback()
                    db.session.close()
                    log.exception(e)
                    if SEND_EXCEPTION_MSG:
                        import sys, traceback
                        exc_type, exc_value, exc_traceback = sys.exc_info()
                        e_text = repr(traceback.format_exception(exc_type, exc_value,
                                                                 exc_traceback))
                        e_text = e_text.replace('\\n\'', '<br/>')
                return result

    celery.Task = ContextTask
    return celery


celery = make_celery(app)

celery.conf.update(
    timezone='Asia/Shanghai',
    beat_schedule={
        'sync_v2_problems_from_lintcode': {
            'task': 'app.tasks.sync_v2_problems_from_lintcode_task',
            'schedule': timedelta(seconds=1800)
        },
        'sync_v2_solutions_from_jiuzhang': {
            'task': 'app.tasks.sync_v2_solutions_from_jiuzhang_task',
            'schedule': timedelta(seconds=1800)
        },
        'add-every-60-seconds': {
            'task': 'app.tasks.sync_task_one_minute',
            'schedule': timedelta(seconds=60)
        },
    },
    task_default_queue='default',
    task_queues=(
        Queue('default', routing_key='app.tasks.#'),
    ),
    task_default_exchange_type='direct',
    task_default_routing_key='tasks.default',
    task_routes=([
                     ('app.tasks.*', {'queue': 'default'}),
                 ],),
    broker_transport_options={
        'max_retries': 3,
        'interval_start': 0,
        'interval_step': 0.2,
        'interval_max': 0.2,
    },
    broker_heartbeat=0
)


@celery.task(name='app.tasks.sync_task_one_minute')
def sync_task_one_minute():
    log.info("sync_task_one_minute")
    return 'sync_task_one_minute'
